package com.swak.entity;

import java.time.LocalDateTime;

import com.swak.App;
import com.swak.Constants;
import com.swak.annotation.Column;

/**
 * 如果使用 cglib 会有问题， 如果setXX 返回值不是void，通过反射设置数据的插件会设值失败
 *
 * @author: lifeng
 * @date: 2020/3/29 11:13
 */
public abstract class IdEntity<T, PK> {
	
	/**
	 * 根主键，默认ID 使用此组件
	 */
	public static final long Root_Id = Constants.ROOT;
	
	/**
	 * 默认的查询条件
	 */
	public static final String DefaultOrderBy = "CREATE_DATE DESC";

	/**
	 * 默认的查询条件
	 */
	public static final String IdOrderBy = "ID DESC";

	/**
	 * 一般作为主键列， 使用此标志表明：自动识别时需要识别为字段
	 */
	@Column
	protected PK id;

	/**
	 * 版本： 可以使用乐观锁来控制并发
	 */
	protected Integer version;

	/**
	 * 删除标志： 逻辑删除
	 */
	@Column(ignore = true)
	protected Boolean delFlag;

	/**
	 * 删除时间: 如果此表需要建立唯一索引，则需要使用此字段，建立组合唯一索引
	 * 可以将delFlag 和 deleteAt 合并为一个字段，后续版本可以优化;
	 * 后续可以将 delAt 改为 long
	 */
	@Column(ignore = true)
	protected LocalDateTime delAt;

	/**
	 * 创建时间
	 */
	protected LocalDateTime createDate;

	/**
	 * 修改时间
	 */
	protected LocalDateTime updateDate;
	
	/**
	 * 合并语句：一般通过使用合并语句来适应： check -》insert or update 的场景
	 * -》 但有时特别的肯定，需要执行 update，此时可以设置为  非 null 值；
	 * -》其他的情况不需要设置；
	 */
	@Column(ignore = true)
	protected Byte mergeFlag;

	/**
	 * 强转为当前对象
	 * 
	 * @return
	 */
	@SuppressWarnings("unchecked")
	protected T as() {
		return (T) this;
	}

	public PK getId() {
		return id;
	}

	public T setId(PK id) {
		this.id = id;
		return as();
	}

	public Integer getVersion() {
		return version;
	}

	public T setVersion(Integer version) {
		this.version = version;
		return as();
	}

	public Boolean getDelFlag() {
		return delFlag;
	}

	public T setDelFlag(Boolean delFlag) {
		this.delFlag = delFlag;
		return as();
	}

	public LocalDateTime getCreateDate() {
		return createDate;
	}

	public T setCreateDate(LocalDateTime createDate) {
		this.createDate = createDate;
		return as();
	}

	public LocalDateTime getUpdateDate() {
		return updateDate;
	}

	public T setUpdateDate(LocalDateTime updateDate) {
		this.updateDate = updateDate;
		return as();
	}

	public LocalDateTime getDelAt() {
		return delAt;
	}

	public T setDelAt(LocalDateTime delAt) {
		this.delAt = delAt;
		return as();
	}
	
	public Byte getMergeFlag() {
		return mergeFlag;
	}

	public T setMergeFlag(Byte mergeFlag) {
		this.mergeFlag = mergeFlag;
		return as();
	}

	/**
	 * 新增操作
	 *
	 * @return 主键
	 */
	public PK prePersist() {
		this.setId(App.genId());
		return this.initDates();
	}

	/**
	 * 初始化时间
	 * 
	 * @return 主键
	 */
	protected PK initDates() {
		this.updateDate = this.createDate = LocalDateTime.now();
		return this.getId();
	}

	/**
	 * 修改操作
	 */
	public void preUpdate() {
		this.updateDate = LocalDateTime.now();
	}

	/**
	 * 删除操作
	 */
	public void preDelete() {
		this.delAt = LocalDateTime.now();
	}
}